From 99dda6fa65f736f1036e0ae8a3bf5061a3f7cfba Mon Sep 17 00:00:00 2001
From: Myy <myy@miouyouyou.fr>
Date: Sun, 23 Jul 2017 15:10:50 +0000
Subject: [PATCH] Reboot patch 1 : The Beginning !

This time, the shutdown member of the MMC platform driver is set
directly. However, the procedure will only do something if the
platform is an ASUS Tinkerboard.

Logs have been added since it seems to *still* not work on some ASUS
Tinkerboard.

Signed-off-by: Myy <myy@miouyouyou.fr>
---
 drivers/mmc/host/dw_mmc-rockchip.c | 33 +++++++++++++++++++++++++++++++++
 drivers/mmc/host/dw_mmc.c          | 31 +++++++++++++++++++++++++++++++
 include/linux/reboot.h             |  3 +++
 kernel/reboot.c                    |  1 +
 4 files changed, 68 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index a3f1c2b3..a09cfe7f 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -19,6 +19,10 @@
 #include "dw_mmc.h"
 #include "dw_mmc-pltfm.h"
 
+// Hack
+#include <linux/regulator/consumer.h>
+#include "../core/core.h"
+
 #define RK3288_CLKGEN_DIV       2
 
 struct dw_mci_rockchip_priv_data {
@@ -365,6 +369,34 @@ static int dw_mci_rockchip_probe(struct platform_device *pdev)
 	return 0;
 }
 
+static void dw_mci_rockchip_platfm_shutdown(struct platform_device *pdev)
+{
+	struct dw_mci *host;
+	struct mmc_host *mmc;
+	int ret;
+
+	if (of_machine_is_compatible("asus,rk3288-tinker")) {
+		printk(KERN_ERR "( Myy ) Asus Reboot patch started !\n");
+		host = platform_get_drvdata(pdev);
+		mmc  = host->slot->mmc;
+
+		mmc_power_off(mmc);
+
+		mdelay(20);
+
+		if (!IS_ERR(mmc->supply.vmmc))
+			ret = regulator_enable(mmc->supply.vmmc);
+
+		if (!IS_ERR(mmc->supply.vqmmc))
+			regulator_set_voltage(mmc->supply.vqmmc, 3000000, 3300000);
+		printk(
+			KERN_ERR "( Myy ) Asus Reboot patch ended !\n"
+			"Voltage set to %d\n", regulator_get_voltage(mmc->supply.vqmmc)
+		);
+	}
+}
+
+
 static int dw_mci_rockchip_remove(struct platform_device *pdev)
 {
 	pm_runtime_get_sync(&pdev->dev);
@@ -385,6 +417,7 @@ static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = {
 static struct platform_driver dw_mci_rockchip_pltfm_driver = {
 	.probe		= dw_mci_rockchip_probe,
 	.remove		= dw_mci_rockchip_remove,
+	.shutdown	= dw_mci_rockchip_platfm_shutdown,
 	.driver		= {
 		.name		= "dwmmc_rockchip",
 		.of_match_table	= dw_mci_rockchip_match,
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a9dfb269..3947a524 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -42,6 +42,10 @@
 
 #include "dw_mmc.h"
 
+// ASUS Hack
+#include <linux/reboot.h>
+#include "../core/core.h"
+
 /* Common flag combinations */
 #define DW_MCI_DATA_ERROR_FLAGS	(SDMMC_INT_DRTO | SDMMC_INT_DCRC | \
 				 SDMMC_INT_HTO | SDMMC_INT_SBE  | \
@@ -2687,6 +2691,31 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+struct dw_mci *mSdhost;
+void setmmcEmergency() {
+	struct mmc_host *mmc;
+	int ret;
+
+	if (of_machine_is_compatible("asus,rk3288-tinker")) {
+		printk(KERN_ERR "( Myy ) Asus Reboot patch started !\n");
+		mmc = mSdhost->slot->mmc;
+		mmc_power_off(mmc);
+		mdelay(20);
+
+		if (!IS_ERR(mmc->supply.vmmc))  {
+			ret = regulator_enable(mmc->supply.vmmc);
+		}
+
+		if (!IS_ERR(mmc->supply.vqmmc))
+			regulator_set_voltage(mmc->supply.vqmmc, 3000000, 3300000);
+		printk(
+			KERN_ERR "( Myy ) Asus Reboot patch ended !\n"
+			"Voltage set to %d\n", regulator_get_voltage(mmc->supply.vqmmc)
+		);
+	}
+}
+EXPORT_SYMBOL(setmmcEmergency);
+
 static int dw_mci_init_slot(struct dw_mci *host)
 {
 	struct mmc_host *mmc;
@@ -2718,6 +2747,8 @@ static int dw_mci_init_slot(struct dw_mci *host)
 		mmc->f_max = freq[1];
 	}
 
+	if (of_find_property(host->dev->of_node, "supports-sd", NULL))
+		mSdhost = host;
 	/*if there are external regulators, get them*/
 	ret = mmc_regulator_get_supply(mmc);
 	if (ret == -EPROBE_DEFER)
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index a7ff409f..44265a80 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -78,6 +78,9 @@ extern void orderly_reboot(void);
  */
 
 extern void emergency_restart(void);
+
+// Wonderful ASUS hack
+extern void setmmcEmergency(void);
 #include <asm/emergency-restart.h>
 
 #endif /* _LINUX_REBOOT_H */
diff --git a/kernel/reboot.c b/kernel/reboot.c
index bd30a973..9f99488f 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -61,6 +61,7 @@ void (*pm_power_off_prepare)(void);
 void emergency_restart(void)
 {
 	kmsg_dump(KMSG_DUMP_EMERG);
+	setmmcEmergency();
 	machine_emergency_restart();
 }
 EXPORT_SYMBOL_GPL(emergency_restart);
-- 
2.13.0

